home *** CD-ROM | disk | FTP | other *** search
/ 5 Star Games: DOS Edition 2 / 5 Star Games - DOS Edition (1995)(Ready to Run).iso / dbc / db_win.c < prev    next >
C/C++ Source or Header  |  1992-04-16  |  49KB  |  1,724 lines

  1. /****************************************************************************/
  2. /*                         DATABOSS MODULE: DB_WIN.C                        */
  3. /****************************************************************************/
  4.  
  5. #include "db_lsc.h"
  6.  
  7. #ifdef __TURBOC__
  8.     #include <conio.h>
  9. #else
  10.     #include <graph.h>
  11.     #include <sys\types.h>
  12.     #define _close(h) close(h)
  13. #endif
  14. #include <dos.h>
  15. #include <io.h>
  16. #include <fcntl.h>
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <sys\stat.h>
  21. #include "db_types.h"
  22. #include "db_conio.h"
  23. #include "db_curs.h"
  24. #include "db_dos.h"
  25. #include "db_file.h"
  26. #include "db_gvar.h"
  27. #include "db_heap.h"
  28. #include "db_key.h"
  29. #include "db_str.h"
  30. #include "db_win.h"
  31.  
  32. /****************************  GLOBAL CONSTANTS   ***************************/
  33.  
  34. attrtable MonoTable =
  35.  {0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
  36.     0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
  37.     0x70,0x08,0x07,0x07,0x07,0x07,0x07,0x07,
  38.     0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
  39.     0x70,0x07,0x08,0x07,0x07,0x07,0x07,0x07,
  40.     0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
  41.     0x70,0x07,0x07,0x08,0x07,0x07,0x07,0x07,
  42.     0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
  43.     0x70,0x07,0x07,0x07,0x08,0x07,0x07,0x07,
  44.     0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
  45.     0x70,0x07,0x07,0x07,0x07,0x08,0x07,0x07,
  46.     0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
  47.     0x70,0x07,0x07,0x07,0x07,0x07,0x08,0x07,
  48.     0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
  49.     0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x77,
  50.     0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,
  51.     0x88,0x87,0x87,0x87,0x87,0x87,0x87,0x87,
  52.     0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,
  53.     0xF0,0x88,0x87,0x87,0x87,0x87,0x87,0x87,
  54.     0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,
  55.     0xF0,0x87,0x88,0x87,0x87,0x87,0x87,0x87,
  56.     0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,
  57.     0xF0,0x87,0x87,0x88,0x87,0x87,0x87,0x87,
  58.     0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,
  59.     0xF0,0x87,0x87,0x87,0x88,0x87,0x87,0x87,
  60.     0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,
  61.     0xF0,0x87,0x87,0x87,0x87,0x88,0x87,0x87,
  62.     0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,
  63.     0xF0,0x87,0x87,0x87,0x87,0x87,0x88,0x87,
  64.     0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,
  65.     0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF7,
  66.     0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0};
  67. attrtable ColorTable =
  68.  {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
  69.     0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
  70.     0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
  71.     0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
  72.     0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
  73.     0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
  74.     0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
  75.     0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
  76.     0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,
  77.     0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
  78.     0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,
  79.     0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,
  80.     0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
  81.     0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
  82.     0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
  83.     0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
  84.     0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
  85.     0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
  86.     0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,
  87.     0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
  88.     0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,
  89.     0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
  90.     0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,
  91.     0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
  92.     0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,
  93.     0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
  94.     0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,
  95.     0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
  96.     0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,
  97.     0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
  98.     0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,
  99.     0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF};
  100.  
  101. /***************************  INTERNAL CONSTANTS  ***************************/
  102.  
  103. #define _Next  'N'
  104. #define _Prev  'P'
  105.  
  106. /**********************  GLOBAL INITIALIZED VARIABLES  **********************/
  107.  
  108. byte vert        = 0;
  109. byte horz        = 1;
  110. bool lcd         = False;
  111. bool goodwrite   = True;
  112. bool posncurs    = False;
  113. bool bg_on       = True;
  114. uchar backfillch = ' ';
  115.  
  116. /****************************  GLOBAL VARIABLES  ****************************/
  117.  
  118. bool      dispbg;
  119. bool      _wondisk;
  120. funcpos   mpath;
  121. funcpos   mdate;
  122. funcpos   mtime;
  123. funcpos   mksta;
  124. wintyp    winscr;
  125. winptr    msgwin;
  126. winptr    firwin;
  127. winptr    curwin;
  128. ptr       actvid;
  129. ptr       savvid;
  130. byte      origm;
  131. byte      origc;
  132. byte      sunposn;
  133. attrtaptr cmono;
  134. byte      scrwid;
  135. byte      scrhgt;
  136. bool      checksnow;
  137. buffering bufInfo;
  138.  
  139. /***************************  INTERNAL VARIABLES  ***************************/
  140.  
  141. static bool initialized = False;
  142.  
  143. /*****************************  IMPLEMENTATION  *****************************/
  144.  
  145. /*-------------------------------------------------------------------
  146.   Returns "True" if End Of File is True and all the buffered info has
  147.   also been read.
  148. -------------------------------------------------------------------*/
  149.  
  150. bool bufEof(int fileHandle)
  151. {
  152.    return((bufInfo.bufPos >= 0) ? ((eof(fileHandle) != -1) && (bufInfo.bufPos > bufInfo.bufEnd)) : (eof(fileHandle) != -1));
  153. }
  154.  
  155.  
  156.  
  157. /*---------------------------------------------------------------------------
  158.   Returns the position in the file as an ofset in bytes of the buffered read
  159.   pointer, (equal to the file position minus the un-read part of the buffer).
  160. ---------------------------------------------------------------------------*/
  161.  
  162. long bufFilePos(int fileHandle)
  163. {
  164.    long filePosition;
  165.  
  166.    filePosition = tell(fileHandle);
  167.    if (bufInfo.bufPos >= 0) filePosition = filePosition - bufInfo.bufEnd + bufInfo.bufPos - 1;
  168.    return(filePosition);
  169. }
  170.  
  171.  
  172.  
  173. /*-------------------------------------------------------------------------
  174.   Get "length" bytes of data from the buffer into "destination".  If the
  175.   buffer does not contain enough data for the request, ("length" bytes),
  176.   then read another block of data from file "filehandle".
  177. -------------------------------------------------------------------------*/
  178.  
  179. void bufBlockRead(int fileHandle, readBuffer destination, word length)
  180. {
  181.    word available, red;
  182.  
  183.    bufInfo.ioRes = 0;
  184.    if (bufInfo.bufPos < 0) read(fileHandle, destination, length);
  185.    else {
  186.       red = 0;
  187.       while(red < length) {
  188.      if (!bufInfo.bufPos) {
  189.         if (!eof(fileHandle)) {
  190.            bufInfo.bufPos = 1;
  191.            bufInfo.bufEnd = read(fileHandle, &bufInfo.dBuf, readBufSize);
  192.            bufInfo.ioRes  = (bufInfo.bufEnd == -1) ? -1 : 0;
  193.         }
  194.         else {
  195.            red            = length;
  196.            bufInfo.bufPos = bufInfo.bufEnd + 1;
  197.         }
  198.      }
  199.      available = bufInfo.bufEnd - bufInfo.bufPos + 1;
  200.      if ((length - red) < available) available = length - red;
  201.      strncpy(&destination[red + 1], &bufInfo.dBuf[bufInfo.bufPos], available);
  202.      red            += available;
  203.      bufInfo.bufPos += available;
  204.      if ((bufInfo.bufPos > bufInfo.bufEnd) && !eof(fileHandle)) bufInfo.bufPos = 0;
  205.       }
  206.    }
  207.    return;
  208. }
  209.  
  210.  
  211.  
  212. /*-------------------------------------------------------------------------
  213.   Calculates the expanded length of the string passed in "inStr".  A string
  214.   may contain special embedded repeat that make its "real" length greater
  215.   than its "apparent" length.
  216. -------------------------------------------------------------------------*/
  217.  
  218. byte eslen(string instr)
  219. {
  220.     byteptr p;
  221.     int count;
  222.  
  223.     count = strlen(instr);
  224.     p = (byteptr) instr;
  225.     do {
  226.         while ((*p != 0) && (*p++ != 255));
  227.         if (*p == 0) return ((byte) count);
  228.         else {
  229.             count -=3;
  230.             if (*(p++) == 0x01) count += *(p++);
  231.         }
  232.     } while (True);
  233. }
  234.  
  235.  
  236.  
  237. /*----------------------------------------------------------
  238.   Return the inverse of the color attribute passed in "attr"
  239. ----------------------------------------------------------*/
  240.  
  241. byte revattr(byte attr)
  242. {
  243.     byte b;
  244.  
  245.     b    = attr & 0x88;
  246.     attr = attr & 0x77;
  247.     return ((byte) (((attr >> 4) | (attr << 4) | b) ^ 0x08));
  248. }
  249.  
  250.  
  251.  
  252. /*---------------------------------------------------------------------
  253.   Returns true if any portion of the two windows "w1" and "w2" overlap.
  254. ---------------------------------------------------------------------*/
  255.  
  256. bool overlap(winptr w1, winptr w2)
  257. {
  258.     int i;
  259.     winptr twptr;
  260.     wintyp twin1,twin2;
  261.  
  262.     twin1 = *w1;
  263.     twin2 = *w2;
  264.     for (i = 1 ; i <= 2 ; i++) {
  265.         twptr = (i == 1) ? &twin1 : &twin2;
  266.         if (twptr->borchrs[0] != 0) {
  267.             (twptr->x)--;
  268.             (twptr->y)--;
  269.             twptr->wid += 2;
  270.             twptr->hgt += 2;
  271.         }
  272.         if (twptr->shadow > 0) {
  273.             switch (sunposn) {
  274.                 case 1 : (twptr->wid)++; (twptr->hgt)++; break;
  275.                 case 2 : (twptr->x)--;   (twptr->hgt)++; break;
  276.                 case 3 : (twptr->x)--;   (twptr->y)--;   break;
  277.                 case 4 : (twptr->wid)++; (twptr->y)--;   break;
  278.             }
  279.         }
  280.     }
  281.     return ((bool) (((int) (twin1.x+twin1.wid-1) >= twin2.x) &&
  282.                                     (twin1.x <= (int) (twin2.x+twin2.wid-1)) &&
  283.                                     ((int) (twin1.y+twin1.hgt-1) >= twin2.y) &&
  284.                                     (twin1.y <= (int) (twin2.y+twin2.hgt-1))));
  285. }
  286.  
  287.  
  288.  
  289. /*--------------------------------------------------------------------------
  290.   "Clips" the co-ordinates "tx","ty" and dimensions "tw","th" to ensure that
  291.   they specify a rectangle that fits within window "winp"
  292. --------------------------------------------------------------------------*/
  293.  
  294. void clip(byte *tx, byte *ty, byte *tw, byte *th, winptr winp)
  295. {
  296.     if (winp != NULL) {
  297.         if (winp->x < 1) {
  298.             *tx = 1;
  299.             *tw = (byte) (winp->x+winp->wid-1);
  300.         }
  301.         else {
  302.             *tx = (byte) winp->x;
  303.             if (*tx > scrwid) *tw = 0;
  304.             else              *tw = ((*tx+winp->wid-1) > scrwid) ? scrwid-*tx+1 : winp->wid;
  305.         }
  306.         if (winp->y < 1) {
  307.             *ty = 1;
  308.             *th = (byte) (winp->hgt+winp->y-1);
  309.         }
  310.         else {
  311.             *ty = (byte) winp->y;
  312.             if (*ty > scrhgt) *th = 0;
  313.             else              *th = ((*ty+winp->hgt-1) > scrhgt) ? scrhgt-*ty+1 : winp->hgt;
  314.         }
  315.     }
  316.     else *tx = *ty = *tw = *th = 0;
  317. }
  318.  
  319.  
  320.  
  321. /*------------------------------------------------------------------------
  322.   Produces, ("mode" = 1) or removes, ("mode" = 0) the shadow effect around
  323.   window "winp".
  324. ------------------------------------------------------------------------*/
  325.  
  326. void shadowwin(byte mode, winptr winp, ptr vram)
  327. {
  328.     byte x1,y2,tx,ty,tw,th;
  329.     wintyp twin;
  330.  
  331.     if ((winp != NULL) && (winp->shadow > 0)) {
  332.         twin = *winp;
  333.         if (twin.borchrs[0] != 0) {
  334.             (twin.x)--;
  335.             (twin.y)--;
  336.             twin.wid += 2;
  337.             twin.hgt += 2;
  338.         }
  339.         switch (sunposn) {
  340.             case 1 :
  341.                 x1 = (byte) (twin.x+twin.wid);
  342.                 y2 = (byte) (twin.y+twin.hgt);
  343.                 twin.x++;
  344.                 twin.y++;
  345.             break;
  346.             case 2 :
  347.                 twin.x--;
  348.                 x1 = (byte) twin.x;
  349.                 y2 = (byte) (twin.y+twin.hgt);
  350.                 twin.y++;
  351.             break;
  352.             case 3 :
  353.                 twin.x--;
  354.                 twin.y--;
  355.                 x1 = (byte) twin.x;
  356.                 y2 = (byte) twin.y;
  357.             break;
  358.             case 4 :
  359.                 twin.y--;
  360.                 x1 = (byte) (twin.x+twin.wid);
  361.                 y2 = (byte) twin.y;
  362.                 twin.x++;
  363.             break;
  364.         }
  365.         clip(&tx,&ty,&tw,&th,&twin);
  366.         if ((x1 >= 1) && (x1 <= scrwid) && (th > 0)) {
  367.             if (mode == 1)
  368.                 dispattr(x1,ty,(*cmono)[twin.shadow],vert,scrwid,winscr.wsize,vram,th);
  369.             else {
  370.                 if (bg_on)
  371.                     restline(x1,ty,th,vert,vram,savvid);
  372.                 else
  373.                     dispattr(x1,ty,15,vert,scrwid,winscr.wsize,vram,th);
  374.             }
  375.         }
  376.         if ((y2 >= 1) && (y2 <= scrhgt) && (tw > 0)) {
  377.             if (mode == 1)
  378.                 dispattr(tx,y2,(*cmono)[twin.shadow],horz,scrwid,winscr.wsize,vram,tw);
  379.             else {
  380.                 if (bg_on)
  381.                     restline(tx,y2,tw,horz,vram,savvid);
  382.                 else
  383.                     dispattr(tx,y2,15,horz,scrwid,winscr.wsize,vram,tw);
  384.             }
  385.         }
  386.     }
  387. }
  388.  
  389.  
  390.  
  391. /*---------------------------------------------------------------------
  392.   Creates 4 lines that correspond to the four sides of the frame around
  393.   a window, (the window border).
  394. ---------------------------------------------------------------------*/
  395.  
  396. void get4sides(winptr winp, string tl, string bl, string rl, string ll)
  397. {
  398.     byte inspos,strplen;
  399.     string ts;
  400.     strptr strp;
  401.     wintyp twin;
  402.  
  403.     if (winp != NULL) {
  404.         twin = *winp;
  405.         twin.x--;
  406.         twin.y--;
  407.         twin.wid += 2;
  408.         twin.hgt += 2;
  409.         memset(tl,twin.borchrs[0],twin.wid); tl[twin.wid] = '\0';
  410.         memset(rl,twin.borchrs[2],twin.hgt); rl[twin.hgt] = '\0';
  411.         memset(bl,twin.borchrs[4],twin.wid); bl[twin.wid] = '\0';
  412.         memset(ll,twin.borchrs[6],twin.hgt); ll[twin.hgt] = '\0';
  413.         tl[0] = twin.borchrs[7]; tl[twin.wid-1] = twin.borchrs[1];
  414.         bl[0] = twin.borchrs[5]; bl[twin.wid-1] = twin.borchrs[3];
  415.         ll[0] = twin.borchrs[7]; ll[twin.hgt-1] = twin.borchrs[5];
  416.         rl[0] = twin.borchrs[1]; rl[twin.hgt-1] = twin.borchrs[3];
  417.         if (twin.title[0] != '\0') {
  418.             strcpy(ts,twin.title);
  419.             switch (twin.titlejus) {
  420.                 case TopLft :
  421.                 case TopCnt :
  422.                 case TopRgt : strp = tl; break;
  423.                 case BotLft :
  424.                 case BotCnt :
  425.                 case BotRgt : strp = bl; break;
  426.                 case LftTop :
  427.                 case LftCnt :
  428.                 case LftBot : strp = ll; break;
  429.                 case RgtTop :
  430.                 case RgtCnt :
  431.                 case RgtBot : strp = rl; break;
  432.             }
  433.             strplen = (byte) strlen(strp);
  434.             if (strplen > 2) {
  435.                 if (strlen(ts)+2 > strplen) ts[strplen-2] = '\0';
  436.                 switch (twin.titlejus) {
  437.                     case TopLft :
  438.                     case BotLft :
  439.                     case LftTop :
  440.                     case RgtTop : inspos = 2; break;
  441.                     case TopCnt :
  442.                     case BotCnt :
  443.                     case LftCnt :
  444.                     case RgtCnt : inspos = (strplen-strlen(ts)+1)/2; break;
  445.                     case TopRgt :
  446.                     case BotRgt :
  447.                     case LftBot :
  448.                     case RgtBot : inspos = strplen-strlen(ts); break;
  449.                 }
  450.                 memmove(&strp[inspos-1],ts,strlen(ts));
  451.             }
  452.         }
  453.     }
  454. }
  455.  
  456.  
  457.  
  458. /*--------------------------------
  459.   Draw the border around a window.
  460. --------------------------------*/
  461.  
  462. void bordwin(winptr winp, ptr vram)
  463. {
  464.     byte tx,ty,tw,th;
  465.     string tln,bln,lln,rln;
  466.     wintyp twin;
  467.  
  468.     if (winp != NULL) {
  469.         twin = *winp;
  470.         get4sides(&twin,tln,bln,rln,lln);
  471.         twin.x--;
  472.         twin.y--;
  473.         twin.wid += 2;
  474.         twin.hgt += 2;
  475.         clip(&tx,&ty,&tw,&th,&twin);
  476.         if (twin.x != tx) {
  477.             strdelete(tln,0,twin.wid-tw);
  478.             strdelete(bln,0,twin.wid-tw);
  479.         }
  480.         else {
  481.             if (twin.wid != tw) {
  482.                 tln[tw] = '\0';
  483.                 bln[tw] = '\0';
  484.             }
  485.         }
  486.         if (twin.y != ty) {
  487.             strdelete(lln,0,twin.hgt-th);
  488.             strdelete(rln,0,twin.hgt-th);
  489.         }
  490.         else {
  491.             if (twin.hgt != th) {
  492.                 lln[th] = '\0';
  493.                 rln[th] = '\0';
  494.             }
  495.         }
  496.         if ((twin.x >= 1) && (twin.x <= (int) scrwid))
  497.             displine(tx,ty,(*cmono)[twin.borcolr],vert,scrwid,winscr.wsize,vram,lln);
  498.         if (((int) (twin.x+twin.wid-1) >= 1) &&
  499.              ((int) (twin.x+twin.wid-1) <= (int) scrwid))
  500.             displine((byte)(tx+tw-1),ty,(*cmono)[twin.borcolr],vert,scrwid,winscr.wsize,vram,rln);
  501.         if ((twin.y >= 1) && (twin.y <= (int) scrhgt))
  502.             displine(tx,ty,(*cmono)[twin.borcolr],horz,scrwid,winscr.wsize,vram,tln);
  503.         if (((int) (twin.y+twin.hgt-1) >= 1) &&
  504.              ((int) (twin.y+twin.hgt-1) <= (int) scrhgt))
  505.             displine(tx,(byte)(ty+th-1),(*cmono)[twin.borcolr],horz,scrwid,winscr.wsize,vram,bln);
  506.     }
  507. }
  508.  
  509.  
  510.  
  511. /*-------------------------------------------
  512.   Restore the background from under a window.
  513. -------------------------------------------*/
  514.  
  515. void restwin(winptr winp)
  516. {
  517.     int loop;
  518.     byte ty,tx,tw,th;
  519.     wintyp twin;
  520.     uchar ts4[5];
  521.  
  522.     if (winp != NULL) {
  523.         twin = *winp;
  524.         if (twin.borchrs[0] != 0) {
  525.             twin.x--;
  526.             twin.y--;
  527.             twin.wid += 2;
  528.             twin.hgt += 2;
  529.         }
  530.         if (((int) (twin.x+twin.wid-1) >= 1) && (twin.x <= (int) scrwid) &&
  531.              ((int) (twin.y+twin.hgt-1) >= 1) && (twin.y <= (int) scrhgt)) {
  532.             clip(&tx,&ty,&tw,&th,&twin);
  533.             if (twin.shadow > 0) shadowwin(0,winp,actvid);
  534.             for (loop=twin.y; loop <= (int) (twin.y+twin.hgt-1); loop++) {
  535.                 if ((loop >= 1) && (loop <= (int) scrhgt)) {
  536.                     if (bg_on) restline(tx,(byte) loop,tw,horz,actvid,savvid);
  537.                     else {
  538.                         strcpy(ts4,"\xFF\x01\x01 ");
  539.                         ts4[2] = tw;
  540.                         displine(tx,(byte) loop,15,horz,scrwid,winscr.wsize,actvid,ts4);
  541.                     }
  542.                 }
  543.             }
  544.         }
  545.     }
  546. }
  547.  
  548.  
  549.  
  550. /*--------------------------------------------------------------------------
  551.   Display window "winp" to destination "vram", (usually video RAM).  Restore
  552.   the cursor associated with the window.
  553. --------------------------------------------------------------------------*/
  554.  
  555. void dispwin(ptr vram, winptr winp)
  556. {
  557.     byte tx,ty,tw,th;
  558.     word wofs;
  559.     ptr wp;
  560.  
  561.     if (winp != NULL) {
  562.         wofs = ((winp->y-winp->my)*winp->mwid+winp->x-winp->mx)*2;
  563.         clip(&tx,&ty,&tw,&th,winp);
  564.  
  565.         if (winp->y <= 0) wofs += (1-winp->y)*winp->wid*2;
  566.         if (winp->x <= 0) wofs += (1-winp->x)*2;
  567.  
  568.         wp = (wofs > 0) ? (byteptr) winp->winblk + wofs : winp->winblk;
  569.  
  570.         dispw(tx,ty,tw,th,(byte)(winp->wid-tw+(winp->mwid-winp->wid)),vram,wp);
  571.         if (winp->borchrs[0] != '\0') bordwin(winp,vram);
  572.         if (winp->shadow > 0)         shadowwin(1,winp,vram);
  573.  
  574.         curfun(_SetCTyp,&winp->curs);
  575.         curfun(_SetCPos,&winp->curs);
  576.     }
  577. }
  578.  
  579.  
  580.  
  581. /*--------------------------------------------
  582.   Re-create the complete background save area.
  583. --------------------------------------------*/
  584.  
  585. void fillsavwin(void)
  586. {
  587.     winptr winp;
  588.  
  589.     initblk(winscr.wsize/2,backfillch,winscr.wincolr,winscr.winblk);
  590.     winp = firwin;
  591.     while (winp != curwin) {
  592.         if (winp->disp) dispwin(savvid,winp);
  593.         winp = winp->nxtwin;
  594.     }
  595. }
  596.  
  597.  
  598.  
  599. /*--------------------------------------------------------------------------
  600.   If a window is switched on the n display it, check for overlapping windows
  601.   to re-display as "winp" may not be the top window.
  602. --------------------------------------------------------------------------*/
  603.  
  604. void dispwindow(winptr winp)
  605. {
  606.     if ((winp != NULL) && winp->disp) {
  607.         if ((winp != curwin) && dispbg) {
  608.             fillsavwin();
  609.             restwin(winp);
  610.             if (curwin->disp && overlap(winp,curwin)) dispwin(actvid,curwin);
  611.         }
  612.         else dispwin(actvid,winp);
  613.     }
  614. }
  615.  
  616.  
  617.  
  618. /*-------------------------------------------------------------------------
  619.   Clear the window contents and re-display the window if it is switched on.
  620. -------------------------------------------------------------------------*/
  621.  
  622. void clrwin(winptr winp)
  623. {
  624.     if (winp != NULL) {
  625.         initblk(winp->wsize/2,' ',winp->wincolr,winp->winblk);
  626.         if (winp->disp) dispwindow(winp);
  627.     }
  628. }
  629.  
  630.  
  631.  
  632. /*-----------------------------------------------------------
  633.   Re-create and display the complete set of viewable windows.
  634. -----------------------------------------------------------*/
  635.  
  636. void dispallwin(void)
  637. {
  638.     fillsavwin();
  639.     dispwin(actvid,&winscr);
  640.     dispwindow(curwin);
  641. }
  642.  
  643.  
  644.  
  645. /*-----------------------------------------------------------------------
  646.   Bring a window to the top of the window stack, display it if necessary.
  647. -----------------------------------------------------------------------*/
  648.  
  649. void selectwin(winptr winp)
  650. {
  651.     if ((winp != NULL) && (winp != curwin)) {
  652.         if (winp == firwin) {
  653.             winp->nxtwin->prvwin = NULL;
  654.             firwin = winp->nxtwin;
  655.         }
  656.         else {
  657.             winp->nxtwin->prvwin = winp->prvwin;
  658.             winp->prvwin->nxtwin = winp->nxtwin;
  659.         }
  660.         winp->prvwin = curwin;
  661.         winp->nxtwin = NULL;
  662.         curwin->nxtwin = winp;
  663.         curwin = winp;
  664.         if (winp->disp) dispallwin();
  665.         else            dispwindow(curwin->prvwin);
  666.     }
  667. }
  668.  
  669.  
  670.  
  671. /*-----------------------------------------------------------
  672.   Scroll the internal area of the window up or down one line.
  673. -----------------------------------------------------------*/
  674.  
  675. void inscroll(byte dirn, winptr winp)
  676. {
  677.     void *blk1, *blk2;
  678.     uchar ts4[5];
  679.  
  680.     if (winp != NULL) {
  681.         strcpy(ts4,"\xFF\x01\x01 ");
  682.         ts4[2] = winp->mwid;
  683.         if (dirn == _Up_) {
  684.             blk1 = winp->winblk;
  685.             blk2 = (byteptr) winp->winblk + winp->mwid*2;
  686.             memmove(blk2,blk1,winp->wsize-(winp->mwid*2));
  687.             strcpy(ts4,"\xFF\x01\x01 ");
  688.             ts4[2] = winp->mwid;
  689.             writewxy(ts4,0,1,1,winp);
  690.         }
  691.         else {
  692.             blk1 = (byteptr) winp->winblk + winp->mwid*2;
  693.             blk2 = winp->winblk;
  694.             memmove(blk2,blk1,winp->wsize-(winp->mwid*2));
  695.             strcpy(ts4,"\xFF\x01\x01 ");
  696.             ts4[2] = winp->mwid;
  697.             writewxy(ts4,0,1,winp->mhgt,winp);
  698.         }
  699.         if (winp->disp) dispwindow(winp);
  700.     }
  701. }
  702.  
  703.  
  704.  
  705. /*--------------------------------------------------------------------------
  706.   Drag the window one line/column up, down, left of right across the screen.
  707. --------------------------------------------------------------------------*/
  708.  
  709. void scrollwin(byte dirn, winptr winp)
  710. {
  711.     bool moved;
  712.     byte tx,ty,tw,th,tor;
  713.     wintyp twin;
  714.     uchar ts4[5];
  715.  
  716.     if ((winp != NULL) && (winp->disp)) {
  717.         moved = (bool) (((dirn==_Up_) && ((int) (winp->y+winp->hgt-1) > 1)) ||
  718.                                         ((dirn==_Down_) && (winp->y < (int) scrhgt)) ||
  719.                                         ((dirn==_Left_) && ((int) (winp->x+winp->wid-1) > 1)) ||
  720.                                         ((dirn==_Right_) && (winp->x < (int) scrwid)));
  721.         if (moved) {
  722.             moved = False;
  723.             if (winp != curwin) hidewin(T_OFF,winp);
  724.             else {
  725.                 if (winp->shadow > 0) shadowwin(0,winp,actvid);
  726.                 twin = *winp;
  727.                 if (twin.borchrs[0] != 0) {
  728.                     twin.x--;
  729.                     twin.y--;
  730.                     twin.wid += 2;
  731.                     twin.hgt += 2;
  732.                 }
  733.                 clip(&tx,&ty,&tw,&th,&twin);
  734.                 switch (dirn) {
  735.                     case _Up_    :
  736.                         ty  = (byte) (twin.y+twin.hgt-1);
  737.                         tor = horz;
  738.                         moved = (bool) ((int) (twin.y+twin.hgt-1) <= (int) scrhgt);
  739.                     break;
  740.                     case _Down_  :
  741.                         ty  = (byte) twin.y;
  742.                         tor = horz;
  743.                         moved = (bool) (twin.y >= 1);
  744.                     break;
  745.                     case _Left_  :
  746.                         tx    = (byte) (twin.x+twin.wid-1);
  747.           tw    = th;
  748.           tor   = vert;
  749.                         moved = (bool) ((int) (twin.x+twin.wid-1) <= (int) scrwid);
  750.                     break;
  751.                     case _Right_ :
  752.                         tx    = (byte) twin.x;
  753.           tw    = th;
  754.           tor   = vert;
  755.                         moved = (bool) (twin.x >= 1);
  756.                     break;
  757.                 }
  758.                 if (moved) {
  759.                     if (bg_on) restline(tx,ty,tw,tor,actvid,savvid);
  760.                     else {
  761.                         strcpy(ts4,"\xFF\x01\x01 ");
  762.                         ts4[2] = tw;
  763.                         displine(tx,ty,15,tor,scrwid,winscr.wsize,actvid,ts4);
  764.                     }
  765.                 }
  766.             }
  767.             switch (dirn) {
  768.                 case _Up_    : winp->my--; winp->y--; winp->curs.crow--; break;
  769.                 case _Down_  : winp->my++; winp->y++; winp->curs.crow++; break;
  770.                 case _Left_  : winp->mx--; winp->x--; winp->curs.ccol--; break;
  771.                 case _Right_ : winp->mx++; winp->x++; winp->curs.ccol++; break;
  772.             }
  773.             if (winp != curwin) hidewin(T_ON,winp);
  774.             else                dispwindow(winp);
  775.         }
  776.     }
  777. }
  778.  
  779.  
  780.  
  781. /*--------------------------------------------------------------------------
  782.   Re-locate the window at he new base co-ordinates, "tx","ty".  The top left
  783.   corner of the window is its anchor point.
  784. --------------------------------------------------------------------------*/
  785.  
  786. void movewin(int tx, int ty, winptr winp)
  787. {
  788.     bool savdisp;
  789.  
  790.     if (winp != NULL) {
  791.         savdisp = winp->disp;
  792.         if (winp->disp) {
  793.             if (winp != curwin) hidewin(T_OFF,winp);
  794.             else                restwin(curwin);
  795.         }
  796.         if ((tx <= (int) scrwid) && ((int) (tx+winp->wid-1) >= 1) &&
  797.                 (ty <= (int) scrhgt) && ((int) (ty+winp->hgt-1) >= 1)) {
  798.             winp->curs.ccol = (byte) (winp->curs.ccol+(tx-winp->x));
  799.             winp->curs.crow = (byte) (winp->curs.crow+(ty-winp->y));
  800.             winp->mx += tx - winp->x;
  801.             winp->my += ty - winp->y;
  802.             winp->x = tx;
  803.             winp->y = ty;
  804.         }
  805.         winp->disp = savdisp;
  806.         dispwindow(winp);
  807.     }
  808. }
  809.  
  810.  
  811.  
  812. /*-----------------------------------------------------------------------
  813.   Switch a window on or off, ("mode" = T_ON or T_OFF), causing the window
  814.   to be displayed or hidden.
  815. -----------------------------------------------------------------------*/
  816.  
  817. void hidewin(bool mode, winptr winp)
  818. {
  819.     if (winp != NULL) {
  820.         if (winp->disp != mode) {
  821.             winp->disp = mode;
  822.             if (!winp->disp) {
  823.                 if (winp == curwin) {
  824.                     restwin(curwin);
  825.                     curfun(_SetCTyp,&hidecurs);
  826.                 }
  827.                 else {
  828.                     fillsavwin();
  829.                     restwin(winp);
  830.                     if (overlap(winp,curwin)) dispwindow(curwin);
  831.                 }
  832.             }
  833.             else dispwindow(winp);
  834.         }
  835.     }
  836. }
  837.  
  838.  
  839.  
  840. /*---------------------------------------
  841.   Expand or contract a window dimensions.
  842. ---------------------------------------*/
  843.  
  844. void resizewin(int tx, int ty, int tw, int th, winptr winp)
  845. {
  846.     bool savdisp;
  847.  
  848.     if (winp != NULL) {
  849.         savdisp = winp->disp;
  850.         if (winp->disp) hidewin(T_OFF,winp);
  851.  
  852.         tw += winp->wid + tx;
  853.         tx  = winp->x   - tx;
  854.         th += winp->hgt + ty;
  855.         ty  = winp->y   - ty;
  856.  
  857.         if ((tx >= winp->mx) && ((tx+tw-1) <= (int) (winp->mx+winp->mwid-1)) &&
  858.                 (ty >= winp->my) && ((ty+th-1) <= (int) (winp->my+winp->mhgt-1)) &&
  859.                 (tw <= (int) winp->mwid) && (tw > 0) &&
  860.                 (th <= (int) winp->mhgt) && (th > 0)) {
  861.             winp->x         = tx;
  862.             winp->y         = ty;
  863.             winp->wid       = (byte) tw;
  864.             winp->hgt       = (byte) th;
  865.             winp->curs.ccol = (byte) winp->x;
  866.             winp->curs.crow = (byte) winp->y;
  867.         }
  868.         if (savdisp) {
  869.             hidewin(T_ON,winp);
  870.             winp->disp = savdisp;
  871.         }
  872.     }
  873. }
  874.  
  875.  
  876.  
  877. /*--------------------------------------
  878.   Switch between 25 and 43/50 line mode.
  879. --------------------------------------*/
  880.  
  881. void togglemode(void)
  882. {
  883. /*   bool saveCheckSnow;           */
  884. /*   cursortyp tcurs;              */
  885. /*                                 */
  886. /*   curfun(_GetCurs,&tcurs);      */
  887. /*   saveCheckSnow = checksnow;    */
  888. /*   textmode(lastmode ^ font8x8); */
  889. /*   textattr(7);                  */
  890. /*   checksnow = saveCheckSnow;    */
  891. /*   dispallwin();                 */
  892. /*   curfun(_SetCPos,&tcurs);      */
  893. /*   return;                       */
  894. }
  895.  
  896.  
  897.  
  898. /*----------------------------------------------------------------------------
  899.   Write the line "wstr" into the window "winp" at window relative co-ordinates
  900.   "wx","wy", in attribute "wa".  If the window is switched on then the change
  901.   is also reflected on the screen.
  902.  
  903.   The global variable "goodwrite" may be set by the programmer.
  904.   "goodwrite" = "true" means that it is not necessary to check for overlapping
  905.   windows, (usually because the write is being done to the top window), this
  906.   is the default state.  "goodwrite" = "false" slows the write consideralby,
  907.   especially if may windows are stored on the window stack because of the
  908.   checks for overlapping screens and subsequent full window re-displays that
  909.   may be necessary.
  910. ----------------------------------------------------------------------------*/
  911.  
  912. void writewxy(string wstr, byte wa, byte wx, byte wy, winptr winp)
  913. {
  914.     if (winp != NULL) {
  915.         if ((wx <= winp->mwid) && (wy <= winp->mhgt)) {
  916.             displine(wx,wy,wa,horz,winp->mwid,winp->wsize,winp->winblk,wstr);
  917.             if (winp->disp) {
  918.                 if (goodwrite) {
  919.                     displine((byte) (winp->mx+wx-1),(byte) (winp->my+wy-1),
  920.                                         (*cmono)[wa],horz,scrwid,winscr.wsize,actvid,wstr);
  921.                     if (winp != curwin)
  922.                         displine((byte) (winp->mx+wx-1),(byte) (winp->my+wy-1),
  923.                                             wa,horz,scrwid,winscr.wsize,savvid,wstr);
  924.                     if (posncurs) {
  925.                         winp->curs.ccol = (byte) (winp->mx+wx+eslen(wstr)-1);
  926.                         winp->curs.crow = (byte) (winp->my+wy-1);
  927.                         curfun(_SetCPos,&winp->curs);
  928.                     }
  929.                 }
  930.                 else dispwindow(winp);
  931.             }
  932.         }
  933.     }
  934.     else displine(wx,wy,(*cmono)[wa],horz,scrwid,winscr.wsize,actvid,wstr);
  935. }
  936.  
  937.  
  938.  
  939. /*--------------------------------------------------------------------------
  940.   Corresponds to "writewxy" above except that only attributes are changed,
  941.   the text in the window is not altered.
  942. --------------------------------------------------------------------------*/
  943.  
  944. void attrwritewxy(byte len, byte wa, byte wx, byte wy, winptr winp)
  945. {
  946.     if (winp != NULL) {
  947.         if ((wx <= winp->mwid) && (wy <= winp->mhgt)) {
  948.             dispattr(wx,wy,wa,horz,winp->mwid,winp->wsize,winp->winblk,len);
  949.             if (winp->disp) {
  950.                 if (goodwrite) {
  951.                     dispattr((byte) (winp->mx+wx-1),(byte) (winp->my+wy-1),
  952.                                         (*cmono)[wa],horz,scrwid,winscr.wsize,actvid,len);
  953.                     if (winp != curwin)
  954.                         dispattr((byte) (winp->mx+wx-1),(byte) (winp->my+wy-1),
  955.                                             wa,horz,scrwid,winscr.wsize,savvid,len);
  956.                     if (posncurs) {
  957.                         winp->curs.ccol = (byte) (winp->mx+wx+len-1);
  958.                         winp->curs.crow = (byte) (winp->my+wy-1);
  959.                         curfun(_SetCPos,&winp->curs);
  960.                     }
  961.                 }
  962.                 else dispwindow(winp);
  963.             }
  964.         }
  965.     }
  966.     else dispattr(wx,wy,(*cmono)[wa],horz,scrwid,winscr.wsize,actvid,len);
  967. }
  968.  
  969.  
  970.  
  971. /*------------------------------------------------------------------------
  972.   Pulls a line of text out of window "winp" into "tscC", and puts the
  973.   corresponding color attributes into "tsa".  "tx" and "ty" are the window
  974.   relative co-ordinates for the start of the line, and "tl" is the desired
  975.   string length.
  976. ------------------------------------------------------------------------*/
  977.  
  978. void getline(byte tx, byte ty, byte tl, string tsc, string tsa, winptr winp)
  979. {
  980.     int b;
  981.     word sofs;
  982.     byte *sptr;
  983.     byte tmpb[512];
  984.  
  985.     if (winp != NULL) {
  986.         sofs = ((ty-1)*winp->wid+(tx-1))*2;
  987.         if (sofs <= winp->wsize) {
  988.             if ((tx+tl-1) > winp->mwid) tl = winp->mwid - tx + 1;
  989.             sptr = (byteptr) winp->winblk + sofs;
  990.             memmove(tmpb,sptr,tl*2);
  991.             sptr = tmpb;
  992.             for (b = 1 ; b <= tl ; b++) {
  993.                 *(tsc++) = *(sptr++);
  994.                 *(tsa++) = *(sptr++);
  995.             }
  996.         }
  997.     }
  998.     *tsc = '\0';
  999.     *tsa = '\0';
  1000. }
  1001.  
  1002.  
  1003.  
  1004. /*-----------------------------------------------------------------------
  1005.   Puts a text string "tsc", and corresponding color attributes,"tsa" as a
  1006.   line into window "winp".  "tx" and "ty" are the window relative
  1007.   co-ordinates for the start of the line, and "tl" is the length.
  1008. -----------------------------------------------------------------------*/
  1009.  
  1010. void putline(byte tx, byte ty, byte tl, string tsc, string tsa, winptr winp)
  1011. {
  1012.     int b;
  1013.     word sofs;
  1014.     strptr sptr,tsp;
  1015.     uchar ts[512];
  1016.  
  1017.     if (winp != NULL) {
  1018.         sofs = ((ty-1)*winp->wid+(tx-1))*2;
  1019.         if (sofs <= winp->wsize) {
  1020.             if ((tx+tl-1) > winp->mwid) tl = winp->mwid - tx + 1;
  1021.             for (b = 1, tsp = ts ; b <= tl ; b++) {
  1022.                 *(tsp++) = *(tsc++);
  1023.                 *(tsp++) = *(tsa++);
  1024.             }
  1025.             sptr = (strptr) winp->winblk + sofs;
  1026.             memmove(sptr,ts,tl*2);
  1027.             if (winp->disp) dispwindow(winp);
  1028.         }
  1029.     }
  1030. }
  1031.  
  1032.  
  1033.  
  1034. /*-------------------------------------------------------------------------
  1035.   Displays the message string "msg", usually in the top rigth corner.  If
  1036.   "w" is not Nil then extra care is taken to move the message to a position
  1037.   that does not overlap window "w".
  1038. -------------------------------------------------------------------------*/
  1039.  
  1040. void message(winptr w, string msg)
  1041. {
  1042.     wintyp tw;
  1043.     int tx,ty,msglen;
  1044.     bool dsp;
  1045.     uchar msgstr[77];
  1046.  
  1047.     strncpy(msgstr,msg,76);
  1048.     msgstr[76] = '\0';
  1049.     msglen = (byte) strlen(msgstr);
  1050.     if (msgwin != NULL) closewin(&msgwin);
  1051.     if (w == NULL) {
  1052.         tw.mx   = 1;
  1053.         tw.my   = 25;
  1054.         tw.mwid = 1;
  1055.         tw.mhgt = 1;
  1056.         w       = &tw;
  1057.     }
  1058.     if ((msglen != 0) && (w != NULL)) {
  1059.         dsp = True;
  1060.         tx = scrwid - msglen + 1 - 4;
  1061.         ty = 1;
  1062.         if ((w->my == 1) && ((int) (w->mx+w->mwid-1) >= tx)) {
  1063.             tx = 1;
  1064.             if ((msglen + 4) > w->mx) {
  1065.                 ty = scrhgt;
  1066.                 if (((int) (w->my+w->mhgt-1) >= ty) && (msglen+4 > w->mx)) {
  1067.                     tx = scrwid - msglen + 1 + 4;
  1068.                     if ((int) (w->mx+w->mwid-1) >= tx) dsp = False;
  1069.                 }
  1070.             }
  1071.         }
  1072.         if (dsp && openwin(0,tx,ty,(byte) (msglen+4),1,79,79,0,"\0┐│┘─└│┌",TopCnt,"")) {
  1073.             msgwin = curwin;
  1074.             writewxy("\x10 ",207,1,1,msgwin);
  1075.             writewxy(msgstr,79,3,1,msgwin);
  1076.             writewxy(" \x11",207,(byte) (msglen+3),1,msgwin);
  1077.             msgwin->disp = True;
  1078.             dispwindow(msgwin);
  1079.         }
  1080.     }
  1081. }
  1082.  
  1083.  
  1084.  
  1085. /*---------------------------------------------------------------------------
  1086.   Highlights a line, (length "l" starting at "tx", "ty"), in window "winp" by
  1087.   temporarily changing its attribute to "a".  If "c" is not 0 then it also
  1088.   temporarily overwrites the text with "c"'s.  As soon as a keypress is
  1089.   detected the original text is restored.
  1090. ---------------------------------------------------------------------------*/
  1091.  
  1092. void hilite(byte tx, byte ty, byte l, byte a, uchar c, winptr winp)
  1093. {
  1094.     string svstr,svatr,newstr;
  1095.     int svlen;
  1096.  
  1097.     if (winp != NULL) {
  1098.         gotoxy(winp->x + tx - 1,winp->y + ty - 1);
  1099.         getline(tx,ty,l,svstr,svatr,winp);
  1100.         svlen = strlen(svstr);
  1101.  
  1102.         if (c != '\0') memset(newstr,c,svlen);
  1103.         else           memmove(newstr,svstr,svlen);
  1104.  
  1105.         newstr[svlen] = '\0';
  1106.         writewxy(newstr,a,tx,ty,winp);
  1107.         while (!kpressed());
  1108.         putline(tx,ty,(byte) strlen(svstr),svstr,svatr,winp);
  1109.     }
  1110. }
  1111.  
  1112.  
  1113.  
  1114. /*---------------------------------------------------------------------------
  1115.   Allocate a window record "winp" and read a window from file "f" into "winp"
  1116. ---------------------------------------------------------------------------*/
  1117.  
  1118. void readwin(int f, winptr *winp)
  1119. {
  1120.     bool tb,sd;
  1121.     wintyp twin;
  1122.     txtblk txtb;
  1123.     string ts;
  1124.     byte tslen;
  1125.     int numr;
  1126.  
  1127.     read(f,(void *)&twin,WinHdrSz1);
  1128.     read(f,&tslen,1);
  1129.     read(f,twin.title,40);
  1130.     twin.title[tslen] = '\0';
  1131.     if (*winp != NULL) {
  1132.         sd = (*winp)->disp;
  1133.         closewin(winp);
  1134.     }
  1135.     else sd = False;
  1136.  
  1137.     if (openwin(twin.wno,twin.mx,twin.my,twin.mwid,twin.mhgt,twin.wincolr,
  1138.                 twin.borcolr,twin.shadow,twin.borchrs,twin.titlejus,twin.title))
  1139.         *winp = curwin;
  1140.  
  1141.     read(f,&tb,1);
  1142.     while (tb) {
  1143.         read(f,(void *)&txtb,3);
  1144.         read(f,&tslen,1);
  1145.         read(f,ts,tslen);
  1146.         ts[tslen] = '\0';
  1147.         if (*winp != NULL) writewxy(ts,txtb.a,txtb.x,txtb.y,*winp);
  1148.         read(f,&tb,1);
  1149.     }
  1150.     if (sd) hidewin(T_ON,*winp);
  1151. }
  1152.  
  1153.  
  1154.  
  1155. /*---------------------------------------
  1156.   Read over / Ignore a window in file "f"
  1157. ---------------------------------------*/
  1158.  
  1159. void readoverwin(int f)
  1160. {
  1161.     bool tb;
  1162.     string ts;
  1163.     byte tslen;
  1164.  
  1165.     read(f,ts,WinHdrSz);
  1166.     read(f,&tb,1);
  1167.     while (tb) {
  1168.         read(f,ts,3);
  1169.         read(f,&tslen,1);
  1170.         read(f,ts,tslen);
  1171.         read(f,&tb,1);
  1172.     }
  1173. }
  1174.  
  1175.  
  1176.  
  1177. /*--------------------------------------------------------------------------
  1178.   Read the header information from the window file "wfil"; includes screen
  1179.   size needed for windows, base color and fill character, background window,
  1180.   and date, time, key status, & datapath variable positions.
  1181. --------------------------------------------------------------------------*/
  1182.  
  1183. bool readwhdr(int wfil, winfrec *wfr)
  1184. {
  1185.     bool fval,tb;
  1186.     int loop;
  1187.     uchar ts[5];
  1188.  
  1189.     fval = True;
  1190.     loop = 1;
  1191.     read(wfil,&wfr->scrmode,1);
  1192.     if (wfr->scrmode == 1)                      wfr->scrmode = 25;
  1193.     if ((wfr->scrmode != 25) && (scrhgt == 25)) togglemode();
  1194.     if (wfr->scrmode > scrhgt) {
  1195.         fval = False;
  1196.         cwrite("\r\n");
  1197.         cwrite(LSC_UnsupportedVideo);
  1198.         sprintf(ts,"%hu",wfr->scrmode);
  1199.         cwrite(ts);
  1200.         delay(4000);
  1201.         cwrite("\r\n");
  1202.     }
  1203.     else {
  1204.         read(wfil,&backfillch,1);
  1205.         read(wfil,&winscr.wincolr,1);
  1206.         wfr->bgw    = NULL;
  1207.         wfr->bfchar = backfillch;
  1208.         wfr->bfcolr = winscr.wincolr;
  1209.         do {
  1210.             read(wfil,&tb,1);
  1211.             switch (loop++) {
  1212.                 case 1 : if (tb) readwin(wfil,&wfr->bgw); break;
  1213.                 case 2 : if (tb) {
  1214.                          read(wfil,(void *)&mdate,sizeof(funcpos));
  1215.                          read(wfil,(void *)&mtime,sizeof(funcpos));
  1216.                          read(wfil,(void *)&mksta,sizeof(funcpos));
  1217.                          read(wfil,(void *)&mpath,sizeof(funcpos));
  1218.                      } break;
  1219.             }
  1220.         } while (tb);
  1221.     }
  1222.     return (fval);
  1223. }
  1224.  
  1225.  
  1226.  
  1227. /*----------------------------------------------------------------------------
  1228.   Attempt to read in a complete window file into the "wfr" window file control
  1229.   record structure.
  1230.  
  1231.   wfr.wfnam   is the name of the disk file of windows.
  1232.   wfr.savattr is used to store the DOS file attributes of wfr.wfnam.
  1233.   wfr.wa      is an array of pointers to the windows read, (max 255 windows).
  1234.               if wfr.wa[i] <> Nil then it points to a valid window.
  1235.   wfr.bfchar,
  1236.   bfcolr,
  1237.   scrmode,
  1238.   bgw         are all set when the window file header is read via "readwhdr".
  1239.  
  1240.   Possible return values are
  1241.       0 - Loaded Successfully.
  1242.       2 - File Not Found.
  1243.       3 - No File Name Supplied.
  1244.       8 - Not Enough Memory To Allocate All Windows.
  1245.      10 - Video mismatch.
  1246.     100 - Disk Read Error.
  1247. ----------------------------------------------------------------------------*/
  1248.  
  1249. int initwin(winfrec *wfr)
  1250. {
  1251.   int b,fval;
  1252.   int wfil;
  1253.   winptr twinp;
  1254.   string tfnam;
  1255.   struct stat statbuf;
  1256.  
  1257.   fval = 0;
  1258.   fsearch(tfnam,wfr->wfnam,lookalong);
  1259.   for (b = 0; b <= MaxWins ; b++) wfr->wa[b] = NULL;
  1260.   wfr->bgw = NULL;
  1261.   wfr->savattr = 0;
  1262.  
  1263.   if (*tfnam != '\0') {
  1264.     wfil = open(tfnam,O_BINARY | O_RDWR, S_IREAD | S_IWRITE);
  1265.     if (wfil != -1) {
  1266.       bufInfo.bufPos = -1;
  1267.       bufInfo.ioRes = 0;
  1268.       fstat(wfil,&statbuf);
  1269.       wfr->savattr = statbuf.st_mode;
  1270.       strcpy(wfr->wfnam,tfnam);
  1271.       if (!readwhdr(wfil,wfr)) fval = 10;
  1272.       while ((fval == 0) && !(eof(wfil))) {
  1273.         twinp = NULL;
  1274.         readwin(wfil,&twinp);
  1275.         wfr->wa[twinp->wno] = twinp;
  1276.         if (twinp == NULL) fval = 8;
  1277.       }
  1278.  
  1279.       if (bufInfo.ioRes < 0) fval = 100;
  1280.       bufInfo.bufPos = -1;
  1281.       _close(wfil);
  1282.       if (fval != 0) {
  1283.         for (b = 1; b <= MaxWins; b++) {
  1284.           if (wfr->wa[b] != NULL) closewin(&wfr->wa[b]);
  1285.         }
  1286.         if (wfr->bgw != NULL) closewin(&wfr->bgw);
  1287.       }
  1288.     }
  1289.     else fval = 2;
  1290.   }
  1291.   else fval = 3;
  1292.   return (fval);
  1293. }
  1294.  
  1295.  
  1296.  
  1297. /*-----------------------------------------------------------------------
  1298.   Attempt to allocate a window.  If successful then the global variable
  1299.   "curwin", which points to the top of the window stack, will be pointing
  1300.   to the newly allocated window.
  1301.   Returns "True" if the windows is set up successfully, otherwise returns
  1302.   "False".
  1303. -----------------------------------------------------------------------*/
  1304.  
  1305. bool openwin(   byte _wno,
  1306.                             int _x, int _y, byte _wid, byte _hgt,
  1307.                             byte _wincolr, byte _borcolr, byte _shadow, border _borchrs,
  1308.                             justified _titlejus, string _title)
  1309. {
  1310.     winptr winp;
  1311.     bool opened;
  1312.  
  1313.     opened = False;
  1314.     if ((_wid >= 1) && (_wid <= scrwid) && (_hgt >= 1) && (_hgt <= scrhgt)) {
  1315.         if ((winp = (winptr) db_malloc(sizeof(*winp))) != NULL) {
  1316.             winp->wno = _wno;
  1317.             winp->mwid = _wid;
  1318.             winp->mhgt = _hgt;
  1319.             winp->wsize = winp->mwid * winp->mhgt * 2;
  1320.             winp->mx = (((_x+_wid-1) < 1) || (_x > (int) scrwid)) ? 1 : _x;
  1321.             winp->my = (((_y+_hgt-1) < 1) || (_y > (int) scrhgt)) ? 1 : _y;
  1322.             if ((winp->origptr = db_malloc(winp->wsize+16))==NULL) db_free(winp);
  1323.             else {
  1324.                 if ((curwin != NULL) && (curwin->disp)) dispwin(savvid,curwin);
  1325.                 winp->winblk   = MK_FP(FP_SEG(winp->origptr) + (FP_OFF(winp->origptr) >> 4) + 1,0);
  1326.                 winp->disp     = False;
  1327.                 winp->x        = winp->mx;
  1328.                 winp->y        = winp->my;
  1329.                 winp->wid      = winp->mwid;
  1330.                 winp->hgt      = winp->mhgt;
  1331.                 winp->wincolr  = _wincolr;
  1332.                 memmove(winp->borchrs,_borchrs,8);
  1333.                 winp->borcolr  = _borcolr;
  1334.                 winp->shadow   = _shadow;
  1335.                 winp->titlejus = (byte) _titlejus;
  1336.                 strcopy(winp->title,_title,0,40);
  1337.                 initblk(winp->wsize/2,' ',winp->wincolr,winp->winblk);
  1338.                 if (firwin == NULL) {
  1339.                     winp->prvwin = NULL;
  1340.                     winp->nxtwin = NULL;
  1341.                     curwin       = winp;
  1342.                     firwin       = winp;
  1343.                 }
  1344.                 else {
  1345.                     curwin->nxtwin = winp;
  1346.                     winp->prvwin   = curwin;
  1347.                     winp->nxtwin   = NULL;
  1348.                     curwin         = winp;
  1349.                 }
  1350.                 winp->curs      = hidecurs;
  1351.                 winp->curs.ccol = (byte) winp->x;
  1352.                 winp->curs.crow = (byte) winp->y;
  1353.                 opened          = True;
  1354.             }
  1355.         }
  1356.     }
  1357.     return (opened);
  1358. }
  1359.  
  1360.  
  1361.  
  1362. /*-----------------------------------------------------------------------
  1363.   Close/Deallocate the window pointed to by "winp" and remove this window
  1364.   from the window stack.
  1365. -----------------------------------------------------------------------*/
  1366.  
  1367. void closewin(winptr *winp)
  1368. {
  1369.     winptr twinp;
  1370.  
  1371.     if (*winp != NULL) {
  1372.         if ((*winp)->disp) hidewin(T_OFF,*winp);
  1373.         db_free((*winp)->origptr);
  1374.         if (*winp == firwin) {
  1375.             if ((*winp)->nxtwin == NULL) {
  1376.                 db_free(*winp);
  1377.                 *winp  = NULL;
  1378.                 firwin = NULL;
  1379.                 curwin = NULL;
  1380.             }
  1381.             else {
  1382.                 twinp          = (*winp)->nxtwin;
  1383.                 db_free(*winp);
  1384.                 *winp          = NULL;
  1385.                 firwin         = twinp;
  1386.                 firwin->prvwin = NULL;
  1387.             }
  1388.         }
  1389.         else {
  1390.             (*winp)->prvwin->nxtwin = (*winp)->nxtwin;
  1391.             if (*winp == curwin) {
  1392.                 curwin = (*winp)->prvwin;
  1393.                 fillsavwin();
  1394.             }
  1395.             else (*winp)->nxtwin->prvwin = (*winp)->prvwin;
  1396.             db_free(*winp);
  1397.             *winp = NULL;
  1398.         }
  1399.         if (curwin != NULL) curfun(_SetCPos,&curwin->curs);
  1400.     }
  1401. }
  1402.  
  1403.  
  1404.  
  1405. /*--------------------------------------
  1406.   Close all windows on the window stack.
  1407. --------------------------------------*/
  1408.  
  1409. void closeallwin(void)
  1410. {
  1411.     cursortyp tcurs;
  1412.  
  1413.     curfun(_GetCurs,&tcurs);
  1414.     while (firwin != NULL) closewin(&firwin);
  1415.     curfun(_SetCPos,&tcurs);
  1416. }
  1417.  
  1418.  
  1419.  
  1420. /*---------------------------------------------------------------
  1421.   Close all windows associated with a window file control record.
  1422. ---------------------------------------------------------------*/
  1423.  
  1424. void disposewf(winfrec *wfr)
  1425. {
  1426.     int b;
  1427.  
  1428.     for (b = 1; b <= MaxWins; b++) {
  1429.         if (wfr->wa[b] != NULL) closewin(&wfr->wa[b]);
  1430.     }
  1431.     if (wfr->bgw != NULL) closewin(&wfr->bgw);
  1432. }
  1433.  
  1434.  
  1435.  
  1436. /*-------------------------------------------------------------------------
  1437.   Read "num" consecutive windows, (begining at window "start"), from window
  1438.   file "wfnam" into the array of window pointers "internalwins".
  1439. -------------------------------------------------------------------------*/
  1440.  
  1441. void readintwin(pathstr wfnam, int start, int num, void *internalwins)
  1442. {
  1443.     int i;
  1444.     int wf;
  1445.     winptr *iwin;
  1446.     winfrec wfr;
  1447.  
  1448.     for (i = 0, iwin = (winptr *) internalwins ; i < num ; i++, iwin++) *iwin = NULL;
  1449.     wf = open(wfnam,O_BINARY | O_RDWR, S_IREAD | S_IWRITE);
  1450.    bufInfo.bufPos = -1;
  1451.     if (readwhdr(wf,&wfr)) {
  1452.         if (wfr.bgw != NULL) closewin(&wfr.bgw);
  1453.         for (i = 1 ; i <= start-1 ; i++) readoverwin(wf);
  1454.         for (i = 0, iwin = (winptr *) internalwins ; i < num ; i++, iwin++) readwin(wf,iwin);
  1455.     }
  1456.    bufInfo.bufPos = -1;
  1457.     _close(wf);
  1458. }
  1459.  
  1460.  
  1461.  
  1462. /*-----------------------------------------------------------------------
  1463.   Save a window to the file "f" at the current position in "f".  "f" must
  1464.   be an open untyped file.
  1465. -----------------------------------------------------------------------*/
  1466.  
  1467. void writewin(int f, winptr winp)
  1468. {
  1469.     bool tb;
  1470.     string ts;
  1471.     strptr tsp;
  1472.     byte tslen;
  1473.     txtblk txtb;
  1474.     byte spc_cnt;
  1475.     int i;
  1476.     largebptr lb;
  1477.  
  1478.     if (winp != NULL) {
  1479.        write(f,(void *)&(*winp),WinHdrSz1);
  1480.         tslen = (byte) strlen(winp->title);
  1481.         write(f,&tslen,1);
  1482.         write(f,winp->title,40);
  1483.         i = 0;
  1484.         lb = winp->winblk;
  1485.         while (i < (winp->mwid*winp->mhgt)) {
  1486.             if (((*lb)[i].vchar != ' ')||((*lb)[i].vattr != winp->wincolr)) {
  1487.                 tb = True;
  1488.                 write(f,&tb,1);
  1489.                 txtb.a = (*lb)[i].vattr;
  1490.                 txtb.y = (byte) ((i/winp->mwid)+1);
  1491.                 txtb.x = (byte) ((i+1) % winp->mwid);
  1492.                 if (txtb.x == 0) txtb.x = winp->mwid;
  1493.                 tsp = ts;
  1494.                 tslen = 0;
  1495.                 spc_cnt = 0;
  1496.                 do {
  1497.                     *(tsp++) = (*lb)[i].vchar;
  1498.                     tslen++;
  1499.                     spc_cnt = (((*lb)[i].vattr == winp->wincolr) && ((*lb)[i].vchar == ' ')) ? spc_cnt+1 : 0;
  1500.                     i++;
  1501.                 } while ((i < (winp->mwid*winp->mhgt)) && (((i+1) % winp->mwid) != 1) &&
  1502.                                 ((*lb)[i].vattr == (*lb)[i-1].vattr) && (spc_cnt <= 5));
  1503.  
  1504.                 if (spc_cnt > 0) tslen -= spc_cnt;
  1505.                 write(f,(void *)&txtb,3);
  1506.                 write(f,&tslen,1);
  1507.                 write(f,ts,tslen);
  1508.             }
  1509.             else i++;
  1510.         }
  1511.         tb = False;
  1512.         write(f,&tb,1);
  1513.     }
  1514. }
  1515.  
  1516.  
  1517.  
  1518. /*----------------------------------------------------------------
  1519.   Checks for command line switches relevant to the DB_WIN library.
  1520. ----------------------------------------------------------------*/
  1521.  
  1522. void anyswitches(void)
  1523. {
  1524.     int i;
  1525.     string ts;
  1526.  
  1527.     checksnow = False;
  1528.     for (i = 1; i < paramcount(); i++) {
  1529.         strcpy(ts,paramstr(i));
  1530.         if ((*ts == '-') || (*ts == '/')) {
  1531.             strdelete(ts,0,1);
  1532.             if (strcmpi(ts,"LCD") == 0) lcd       = True;
  1533.             if (strcmpi(ts,"CS") == 0)  checksnow = True;
  1534.         }
  1535.     }
  1536. }
  1537.  
  1538.  
  1539.  
  1540. /*------------------------------------------
  1541.   Clear out the window background save area.
  1542. ------------------------------------------*/
  1543.  
  1544. void clrback(void)
  1545. {
  1546.     initblk(winscr.wsize/2,' ',15,winscr.winblk);
  1547. }
  1548.  
  1549.  
  1550.  
  1551. /*----------------------------------------------------------------------
  1552.   Do a "ClrScr" as well as clearing out the window background save area.
  1553. ----------------------------------------------------------------------*/
  1554.  
  1555. void clrscrandback(void)
  1556. {
  1557.     clrscr();
  1558.     backfillch = ' ';
  1559.     winscr.wincolr = 15;
  1560.     clrback();
  1561. }
  1562.  
  1563.  
  1564.  
  1565. /*-------------------------------------------------------------------------
  1566.   Change the base color of a window.  If the window is switched on then the
  1567.   change will update the display.
  1568. -------------------------------------------------------------------------*/
  1569.  
  1570. void colorwin(byte tcolr, winptr winp)
  1571. {
  1572.     int i;
  1573.     largebptr lb;
  1574.  
  1575.     lb = winp->winblk;
  1576.     for (i = 0 ; i < (winp->wsize/2) ; i++) {
  1577.         if ((*lb)[i].vattr == winp->wincolr) (*lb)[i].vattr = tcolr;
  1578.     }
  1579.     winp->wincolr = tcolr;
  1580.     if (winp->disp) dispwindow(winp);
  1581. }
  1582.  
  1583.  
  1584.  
  1585. /*------------------------------------------------------------------------
  1586.   Go to another valid window in the window file.  If "dirn" is 1 then look
  1587.   for the next window, if "dirn" is -1 look for the previous window.
  1588. ------------------------------------------------------------------------*/
  1589.  
  1590. int nextw(int start, int dirn, winfrec *w)
  1591. {
  1592.     int b;
  1593.  
  1594.     b = start + dirn;
  1595.     while ((b < MaxWins) && (b > 1) && (w->wa[b] == NULL)) b += dirn;
  1596.     return (((b > MaxWins)||(b < 1)||(w->wa[b] == NULL)) ? start : b);
  1597. }
  1598.  
  1599.  
  1600.  
  1601. /*-------------------------------------------------------------------------
  1602.   Visually select a window from those loaded into the window file structure
  1603.   "w".  To avoid picking a specific window, (usually the current one), pass
  1604.   its window number multiplied by -1 in "thiswin".
  1605. -------------------------------------------------------------------------*/
  1606.  
  1607. byte pickwin(int thiswin, winfrec *w)
  1608. {
  1609.     int avoid,fval,low,high,loop;
  1610.     uchar ukey;
  1611.     int nxtdirn;
  1612.  
  1613.     avoid = (thiswin > 0) ? 0 : -thiswin;
  1614.     low = 1;
  1615.     while ((w->wa[low] == NULL) && (low < MaxWins)) low++;
  1616.     high = MaxWins;
  1617.     while ((w->wa[high] == NULL) && (high > 0)) high--;
  1618.     if (w->wa[low] != NULL) {
  1619.         for (loop = low; loop <= abs(thiswin); loop++) hidewin(T_OFF,w->wa[loop]);
  1620.         ukey = ' ';
  1621.         loop = (avoid <= low) ? nextw(avoid,1,w) : nextw(avoid,-1,w);
  1622.         if (loop == avoid) loop = 0;
  1623.         while ((loop > 0) && (ukey != Enter)) {
  1624.             hidewin(T_ON,w->wa[loop]);
  1625.             ukey = getkey();
  1626.             if ((ukey >= 'a') && (ukey <= 'z')) ukey -= 'a'-'A';
  1627.             hidewin(T_OFF,w->wa[loop]);
  1628.             switch (ukey) {
  1629.                 case _Prev  :
  1630.                 case UArr   :
  1631.                 case LArr   : if (loop > low) loop = nextw(loop,-1,w); nxtdirn = -1; break;
  1632.                 case _Next  :
  1633.                 case DArr   :
  1634.                 case RArr   : if (loop < high) loop = nextw(loop,1,w); nxtdirn = 1; break;
  1635.                 case Home   : loop = low; nxtdirn = 1; break;
  1636.                 case EndKey : loop = high; nxtdirn = -1; break;
  1637.                 case Esc    : loop = 0; break;
  1638.             }
  1639.             if ((loop != 0) && (loop == avoid)) {
  1640.                 loop = nextw(loop,nxtdirn,w);
  1641.                 if (loop == avoid) loop = nextw(loop,-nxtdirn,w);
  1642.             }
  1643.         }
  1644.         fval = loop;
  1645.         for (loop = low; loop <= abs(thiswin); loop++) hidewin(T_ON,w->wa[loop]);
  1646.     }
  1647.     else fval = 0;
  1648.     return ((byte) fval);
  1649. }
  1650.  
  1651. /**********************  UNIT INITIALIZATION/EXIT CODE  *********************/
  1652.  
  1653.  
  1654.  
  1655. /*----------------------------------------------------------------------
  1656.   Automatic unit cleanup on termination.
  1657.   Return the video mode to the way it was before the program that "uses"
  1658.   DB_WIN began execution, and free the background save area.
  1659. ----------------------------------------------------------------------*/
  1660.  
  1661. void db_win_exit(void)
  1662. {
  1663.     byte tb,mode;
  1664.  
  1665.     textattr(origc);
  1666.     getscreeninfo(&mode,&tb,&tb,&tb);
  1667.     if (mode != origm) textmode(origm);
  1668.     db_free(winscr.origptr);
  1669. }
  1670.  
  1671.  
  1672.  
  1673. /*-------------------------------------------------------------------------
  1674.   DB_WIN unit initialisation.
  1675.  
  1676.   Initialize global variables.
  1677.   Determine and save the current video mode, (including screen limits).
  1678.   Look for command line switches that may override auto detection routines.
  1679.   Allocate memory for the window background area.
  1680.   Initialise the window stack pointers.
  1681. -------------------------------------------------------------------------*/
  1682.  
  1683. void db_win_init(void)
  1684. {
  1685.     if (!initialized) {
  1686.         initialized = True;
  1687.         db_curs_init();
  1688.         db_gvar_init();
  1689.         db_heap_init();
  1690.         db_key_init();
  1691.       bufInfo.bufPos = -1;
  1692.         _wondisk = False;
  1693.         dispbg = True;
  1694.         sunposn = 1;
  1695.         getscreeninfo(&origm,&scrwid,&scrhgt,&origc);
  1696.         textattr(15);
  1697.         cmono = (attrtable *)(((origm==0)||(origm==2)||(origm==7)) ? MonoTable :ColorTable);
  1698.         actvid = MK_FP((origm == 7) ? 0xB000 : 0xB800,0);
  1699.         anyswitches();
  1700.         if (lcd) cmono = (attrtable *) MonoTable;
  1701.         firwin = curwin = msgwin = NULL;
  1702.         winscr.disp     = True;
  1703.         winscr.mx       = 1;
  1704.       winscr.my       = 1;
  1705.       winscr.mwid     = 80;
  1706.       winscr.mhgt     = 50;
  1707.         winscr.x        = 1;
  1708.       winscr.y        = 1;
  1709.       winscr.wid      = 80;
  1710.       winscr.hgt      = 50;
  1711.         winscr.shadow   = 0;
  1712.         memmove(winscr.borchrs,"\0       ",8);
  1713.         winscr.wincolr  = 15;
  1714.         winscr.wsize    = winscr.mwid * winscr.mhgt * 2;
  1715.         winscr.origptr  = db_malloc(winscr.wsize+16);
  1716.         winscr.winblk   = MK_FP(FP_SEG(winscr.origptr) + (FP_OFF(winscr.origptr) >> 4) + 1,0);
  1717.         savvid          = winscr.winblk;
  1718.         initblk(winscr.wsize/2,backfillch,winscr.wincolr,winscr.winblk);
  1719.         atexit(db_win_exit);
  1720.     }
  1721. }
  1722.  
  1723. /*****************************  END OF DB_WIN.C  ****************************/
  1724.